package com.bawei.network

import android.os.Environment
import com.alibaba.android.arouter.launcher.ARouter
import com.blankj.utilcode.util.EncryptUtils
import com.tencent.mmkv.MMKV
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * 网络管理对象
 */
object HttpManager {

    fun getOkHttpClient(type: HttpInterceptorType): OkHttpClient{
        var okhttpBuilder = OkHttpClient.Builder()
        //设置日志拦截器并添加开关
        if(BuildConfig.isOpenLog){
            okhttpBuilder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
        }
        //添加不同拦截器
        when(type){
            HttpInterceptorType.SIGN -> {
                //设置连接超时和读取超时
                okhttpBuilder.connectTimeout(10, TimeUnit.SECONDS)
                okhttpBuilder.readTimeout(10, TimeUnit.SECONDS)
                //添加签名拦截器
                okhttpBuilder.addInterceptor(getSignInterceptor())
            }
            HttpInterceptorType.TOKEN -> {
                //设置连接超时和读取超时
                okhttpBuilder.connectTimeout(10, TimeUnit.SECONDS)
                okhttpBuilder.readTimeout(10, TimeUnit.SECONDS)
                //添加Token拦截器
                okhttpBuilder.addInterceptor(getTokenInterceptor())
            }
            HttpInterceptorType.INTERFACE -> {
                //设置连接超时和读取超时
                okhttpBuilder.connectTimeout(10, TimeUnit.SECONDS)
                okhttpBuilder.readTimeout(10, TimeUnit.SECONDS)
                //设置拦截器
                okhttpBuilder.addInterceptor(getTokenInterceptor())
                okhttpBuilder.addInterceptor(getSignInterceptor())
            }
            HttpInterceptorType.UPLOAD -> {
                //设置连接超时和读取超时
                okhttpBuilder.connectTimeout(3, TimeUnit.MINUTES)
                okhttpBuilder.readTimeout(3, TimeUnit.MINUTES)
            }
        }

        //添加服务端错误返回拦截
        okhttpBuilder.addInterceptor(getServerErrorInterceptor())
        return okhttpBuilder.build()
    }

    /**
     * 获取网络缓存文件
     */
    private fun getNetCacheFile(): File? {
        try {
            //获取外部SD卡目录
            val dirFile = Environment.getExternalStorageDirectory()
            if (dirFile.exists()) {
                val cacheDirPath = "${dirFile.absolutePath}/netCacheFile"
                var cacheFile = File(cacheDirPath)
                if (!cacheFile.exists()) {
                    cacheFile = File(cacheDirPath)
                }
                return cacheFile
            }
            //获取内部存储目录
            return File("${Environment.getDownloadCacheDirectory().absolutePath}/netCacheFile")
        } catch (e: Exception) {
            return null
        }
    }

    /** 获取一个SSLSocketFactory */
    private val sSLSocketFactory: SSLSocketFactory
        get() = try {
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(trustManager), SecureRandom())
            sslContext.socketFactory
        } catch (e: Exception) {
            throw RuntimeException(e)
        }

    /** 获取一个忽略证书的X509TrustManager */
    private val trustManager: X509TrustManager
        get() = object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }

    /**
     * 网络缓存拦截器
     */
    private fun getNetCacheInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                var oldRequest = chain.request()
                var reqUrl = oldRequest.url
                //需要根据业务添加白名单
                if (!reqUrl.encodedPath.contains("user/login")
                    || !reqUrl.encodedPath.contains("user/register")
                ) {
                    var newRequest = oldRequest.newBuilder().header("Cache-Control", "max-age=3600").build() //缓存1小时
                    return chain.proceed(newRequest)
                }
                return chain.proceed(oldRequest)
            }
        }
    }

    /**
     * token拦截器
     */
    private fun getTokenInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                var token = MMKV.defaultMMKV().decodeString("token") //MMKV采用的是内存映射来实现的，性能高
                if (!token.isNullOrEmpty()) {
                    var newRequest = chain.request().newBuilder().header("token", token).build()
                    var response = chain.proceed(newRequest)
                    //登录失效，需要跳转到登录页面
                    if (response.code == 403) {
                        ARouter.getInstance().build("/activity/login").navigation()
                    }
                    return response
                }
                return chain.proceed(chain.request())
            }
        }
    }

    /**
     * 签名拦截器
     */
    private fun getSignInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                var oldRequest = chain.request()
                try {
                    var builder = oldRequest.newBuilder()
                    builder.url(oldRequest.url)
                    builder.headers(oldRequest.headers)
                    //获取参数JSON
                    var buf = Buffer()
                    var reqBody = oldRequest.body
                    reqBody?.writeTo(buf)
                    var bodyStr = buf.toString()
                    buf.close()
                    bodyStr = bodyStr.substring(bodyStr.indexOf("{"), bodyStr.lastIndexOf("}") + 1)
                    var reqJsonObj = JSONObject(bodyStr)
                    //拼接所有参数值
                    var buffer = StringBuffer()
                    var keys = reqJsonObj.keys()
                    while (keys.hasNext()){
                        buffer.append(reqJsonObj.getString(keys.next()))
                    }
                    //使用MD5加密
                    var signMd5 = getMd5Encrypt(buffer.toString())
                    reqJsonObj.put("sign", signMd5)
                    //创建新的RequestBody
                    var newJson = reqJsonObj.toString()
                    var newBody = newJson.toRequestBody("application/json;charset=utf-8".toMediaTypeOrNull())
                    builder.post(newBody)
                    var newRequest = builder.build()
                    return chain.proceed(newRequest)
                } catch (e: Exception) {
                    e.printStackTrace()
                    return chain.proceed(oldRequest)
                }
            }
        }
    }

    /**
     * 服务器端Error拦截器
     */
    private fun getServerErrorInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                val oldResponse = chain.proceed(chain.request())
                var builder = oldResponse.newBuilder()
                if (oldResponse.code == 500) {
                    var newJson = JSONObject()
                    newJson.put("statuesCode","500")
                    newJson.put("msg","接口异常，请联系客服！")
                    var body = newJson.toString().toResponseBody("application/json;charset=utf-8".toMediaTypeOrNull())
                    builder.body(body)
                }
                return builder.build()
            }
        }
    }



    private fun getMd5Encrypt(originStr: String): String{
        return EncryptUtils.encryptMD5ToString("${originStr}tamboo").lowercase()
    }


    //获取Retrofit
    fun getRetrofit(type: HttpInterceptorType): Retrofit {
        var retrofitBuilder = Retrofit.Builder()
        retrofitBuilder.baseUrl(BuildConfig.BASE_URL)
        retrofitBuilder.client(getOkHttpClient(type))
        retrofitBuilder.addConverterFactory(GsonConverterFactory.create())
        return retrofitBuilder.build()
    }

    //获取接口实例对象
    fun <T> createApi(clazz: Class<*>, type: HttpInterceptorType): T{
        return getRetrofit(type).create(clazz) as T
    }




}